/*
 * 版权所有 (C) 2015 知启蒙(ZHIQIM) 保留所有权利。[遇见知启蒙，邂逅框架梦]
 * 
 * https://zhiqim.org/project/zhiqim_framework/zhiqim_zml.htm
 *
 * Zhiqim Zml is licensed under Mulan PSL v2.
 * You can use this software according to the terms and conditions of the Mulan PSL v2.
 * You may obtain a copy of Mulan PSL v2 at:
 *          http://license.coscl.org.cn/MulanPSL2
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 * See the Mulan PSL v2 for more details.
 */
package org.zhiqim.zml.statement;

import java.util.Iterator;
import java.util.List;

import org.zhiqim.kernel.model.maps.HashMapSO;
import org.zhiqim.kernel.model.maps.MapSO;
import org.zhiqim.kernel.util.Arrays;
import org.zhiqim.kernel.util.Strings;
import org.zhiqim.zml.Expression;
import org.zhiqim.zml.ExpressionParser;
import org.zhiqim.zml.Statement;
import org.zhiqim.zml.StatementNesting;
import org.zhiqim.zml.StatementParser;
import org.zhiqim.zml.ZmlVariable;
import org.zhiqim.zml.Zmls;
import org.zhiqim.zml.exception.StatementException;
import org.zhiqim.zml.statement._Break.BreakException;
import org.zhiqim.zml.statement._Continue.ContinueException;
import org.zhiqim.zml.statement._Return.ReturnException;

/**
 * 迭代语句，格式为：<#for item : list></#for>或<#for (item : list)></#for>
 *
 * @version v1.0.0 @author zouzhigang 2014-3-21 新建与整理
 */
public class _For extends Statement implements StatementNesting
{
    private String itemVariableName;
    private Expression _expression;
    private List<Statement> stmtList;
    private boolean isBeginExclusiveLine = false;
    
    private transient String content;
    private transient int contentBeginIndex;
    
    @Override
    public boolean isNesting()
    {
        return true;
    }
    
    @Override
    public boolean isExclusiveLine() throws StatementException
    {
        return super.isExclusiveLine()?isBeginExclusiveLine:false;
    }
    
    @Override
    public void parseStatement() throws StatementException
    {
        String s = Strings.trim(getStatement(), FOR_BEGIN, FOR_END);
        int ind = s.indexOf(TAG_END);
        if (ind == -1)
            throw new StatementException(this, FOR + "未找到单行结束符");

        String forEach = s.substring(0, ind).trim();
        if (forEach.startsWith("("))
        {//有(开头，则认为格式为for (item : list)
            forEach = Strings.trim(forEach, "(", ")").trim();
        }
        //支持格式for (var item : list)格式，去除var定义
        forEach = Strings.trimLeft(forEach, "var ").trim();
        int index = forEach.indexOf(FOR_SEPARATOR);
        if (index == -1)
            throw new StatementException(this, FOR + "未找到节点定义符");
        
        //变量
        itemVariableName = forEach.substring(0, index).trim();
        
        try
        {
            String expression = forEach.substring(index + FOR_SEPARATOR.length()).trim();
            _expression = ExpressionParser.parseExpression(expression);
        }
        catch(Exception e)
        {
            throw new StatementException(this, FOR + e.getMessage());
        }
        
        //对_for内的内容进行嵌套检查，得到嵌套语句列表
        content = s.substring(ind + 1);
        int brNum = Strings.getStartsWithBrNum(content);
        if (brNum > 0)
        {//删除<#for item : list>之后的首个\r\n
            content = content.substring(brNum);
        }
        
        isBeginExclusiveLine = brNum > 0;
        contentBeginIndex = getBeginIndex() + FOR_BEGIN.length() + ind + 1 + brNum;
        
        //删除</#for>之前的\r\n之后的空白
        content = Zmls.removeRightMaybeEmptyBlank(content);
        
        stmtList = StatementParser.parseStatementNesting(this);
        content = null;//清除临时数据
    }
    
    @Override
    public String process(ZmlVariable variableMap) throws StatementException
    {
        Object value = null;
        
        try
        {
            value = _expression.build(variableMap);
        }
        catch(Exception e)
        {
            throw new StatementException(this, FOR + e.getMessage(), e);
        }
        
        if (value == null)
            return null;//无变量，直接返回null
        
        if (!(value instanceof Iterator) && !(value instanceof Iterable) && !value.getClass().isArray())
            throw new StatementException(this, FOR + "对象不支持迭代");
        
        try
        {//循环处理
            StringBuilder strb = new StringBuilder();
            if (value.getClass().isArray())
            {
                Object[] objs = Arrays.toArray(value);
                for (int i=0;i<objs.length;i++)
                {
                    int status = each(objs[i], i, variableMap, strb);
                    if (status == 1)
                        break;
                    
                    if (status == 2)
                        continue;
                }
            }
            else
            {
                Iterator<?> it = null;
                if (value instanceof Iterable)
                    it = ((Iterable<?>)value).iterator();
                else
                    it = (Iterator<?>)value;
                
                for (int i=0;it.hasNext();i++)
                {
                    Object obj = it.next();
                    
                    int status = each(obj, i, variableMap, strb);
                    if (status == 1)
                        break;
                    
                    if (status == 2)
                        continue;
                }
            }
            
            if (isEndBreak())
            {//如果结束是独占一行，则删除最后的回车 TODO
                int length = strb.length();
                if (length > 0 && (strb.charAt(length-1) == _CR_ || strb.charAt(length-1) == _LF_))
                    strb.setLength(length-1);
                    
                length = strb.length();
                if (length > 0 && (strb.charAt(length-1) == _CR_ || strb.charAt(length-1) == _LF_))
                    strb.setLength(length-1);
            }

            return strb.toString();
        }
        catch(ReturnException e)
        {//通过异常方式给外面的函数提供返回值
            throw e;
        }
        catch(Exception e)
        {
            throw new StatementException(this, FOR + e.getMessage(), e);
        }
    }
    
    private int each(Object obj, int index, ZmlVariable variableMap, StringBuilder strb) throws StatementException
    {
        //定义局部变量
        MapSO localMap = new HashMapSO(2);
        localMap.put(itemVariableName, obj);
        localMap.put(itemVariableName+"_index", index);
        variableMap.addLocalVariable(localMap);
        
        try
        {
            //循环处理语句列表
            StatementParser.processStatementList(stmtList, variableMap, strb);
        }
        catch (BreakException e) 
        {
            return 1;
        }
        catch (ContinueException e) 
        {
            return 2;
        }
        finally
        {//清除局部变量
            variableMap.removeLocalVariable(localMap);
            localMap.clear();localMap = null;
        }
        
        return 0;
    }
    
    /**********************************************/
    //两个临时数据，用于语句解析成嵌套语句列表
    /**********************************************/
    
    @Override
    public String getContent()
    {
        return content;
    }
    
    @Override
    public int getContentBeginIndex()
    {
        return contentBeginIndex;
    }
    
    @Override
    public String getPrevStatement(Statement stmt) throws StatementException
    {
        int ind = stmtList.indexOf(stmt);
        if (ind <= 0)
            return null;
        
        return stmtList.get(ind-1).getStatement();
    }
    
    @Override
    public String getNextStatement(Statement stmt) throws StatementException
    {
        int ind = stmtList.indexOf(stmt);
        if (ind == -1 || ind >= stmtList.size()-1)
            return null;
        
        return stmtList.get(ind+1).getStatement();
    }
}
